/*
 * Copyright (c) 2006-2020, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2020-05-21     chenhy       the first version
 */
#include "board.h"
#include <string.h>
#include <stdio.h>
#include "adc.h"
#include "mem.h"

ADC_HandleTypeDef hadc1;
uint16_t adc_sample[4];
int adc_init(void)
{
  ADC_ChannelConfTypeDef config;
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  hadc1.Init.LowPowerAutoPowerOff = DISABLE;
  hadc1.Init.LowPowerAutoWait = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  hadc1.Init.SamplingTimeCommon = ADC_SAMPLETIME_239CYCLES_5;
  HAL_ADC_DeInit(&hadc1);
  HAL_ADC_Init(&hadc1);
  HAL_ADCEx_Calibration_Start(&hadc1);
  config.Rank = ADC_RANK_CHANNEL_NUMBER;
  config.Channel = ADC_CHANNEL_4;
  HAL_ADC_ConfigChannel(&hadc1, &config);
  config.Channel = ADC_CHANNEL_5;
  HAL_ADC_ConfigChannel(&hadc1, &config);
  config.Channel = ADC_CHANNEL_6;
  HAL_ADC_ConfigChannel(&hadc1, &config);
  config.Channel = ADC_CHANNEL_7;
  HAL_ADC_ConfigChannel(&hadc1, &config);
  memset(adc_sample, 0, sizeof(adc_sample));
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_sample, 4);
  return 0;
}
INIT_APP_EXPORT(adc_init);

void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)
{
  GPIO_InitTypeDef gpio_init;
  static DMA_HandleTypeDef hdma_adc1;
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_ADC1_CLK_ENABLE();
  __HAL_RCC_DMA1_CLK_ENABLE();

  gpio_init.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
  gpio_init.Mode = GPIO_MODE_ANALOG;
  gpio_init.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &gpio_init);

  hdma_adc1.Instance = DMA1_Channel2;
  hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
  hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
  hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
  hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
  hdma_adc1.Init.Mode = DMA_CIRCULAR;
  hdma_adc1.Init.Priority = DMA_PRIORITY_MEDIUM;
  HAL_DMA_Init(&hdma_adc1);
  __HAL_DMA1_REMAP(HAL_DMA1_CH2_ADC);
  __HAL_LINKDMA(hadc, DMA_Handle, hdma_adc1);

  HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 2, 0);
  HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
}

void HAL_ADC_MspDeInit(ADC_HandleTypeDef *hadc)
{
  __HAL_RCC_ADC1_FORCE_RESET();
  __HAL_RCC_ADC1_RELEASE_RESET();
  __HAL_RCC_ADC1_CLK_DISABLE();
  HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
  if(hadc->DMA_Handle != 0) HAL_DMA_DeInit(hadc->DMA_Handle);
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
  memcpy(sample_data, adc_sample, sizeof(adc_sample));
}
